﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
namespace Hellquest
{
    public class Animation : ICloneable
    {
        Rectangle[] frames;
        public int[] FPS;
        public Vector2[] Offsets;

        int framesPerSecond;
        TimeSpan frameLength;
        TimeSpan frameTimer;
        int currentFrame;
        int frameWidth;
        int frameHeight;

        public int FramesPerSecond
        {
            get { return framesPerSecond; }
            set
            {
                if (value < 1)
                    framesPerSecond = 1;
                else
                    framesPerSecond = value;
                frameLength = TimeSpan.FromSeconds(1f / (double)framesPerSecond);
            }
        }

        public int FrameCount
        {
            get { return frames.Length; }
        }

        public Rectangle CurrentFrameRect
        {
            get { return frames[currentFrame]; }
        }
        public int CurrentFrame
        {
            get { return currentFrame; }
            set
            {
                currentFrame = (int)MathHelper.Clamp(value, 0, frames.Length - 1);
            }
        }
        public int FrameWidth
        {
            get { return frameWidth; }
        }
        public int FrameHeight
        {
            get { return frameHeight; }
        }

        public bool PlayOnce;

        public bool IsFinished
        {
            get;
            private set;
        }

        private Vector2 drawingOffset;
        public Vector2 DrawingOffset { get { return drawingOffset + Offsets[currentFrame]; } }

        public Animation(int frameCount, int frameWidth, int frameHeight, int xOffset, 
            int yOffset, bool _playOnce = false, int _framePerSecond = 10)
        {
            frames = new Rectangle[frameCount];
            FPS = new int[frameCount];
            Offsets = new Vector2[frameCount];

            this.frameWidth = frameWidth;
            this.frameHeight = frameHeight;
            for (int i = 0; i < frameCount; i++)
            {
                frames[i] = new Rectangle(
                    xOffset + (frameWidth * i),
                    yOffset,
                    frameWidth,
                    frameHeight);
                FPS[i] = _framePerSecond;
                Offsets[i] = Vector2.Zero;
            }
            FramesPerSecond = _framePerSecond;
            PlayOnce = _playOnce;
            drawingOffset = Vector2.Zero;
            

            Reset();
        }

        public Animation(int frameCount, int frameWidth, int frameHeight, int xOffset, 
            int yOffset, Vector2 _drawingOffset, bool _playOnce = false, int _framePerSecond = 10)
        {
            frames = new Rectangle[frameCount];
            this.frameWidth = frameWidth;
            this.frameHeight = frameHeight;
            Offsets = new Vector2[frameCount];
            FPS = new int[frameCount];
            for (int i = 0; i < frameCount; i++)
            {
                frames[i] = new Rectangle(
                xOffset + (frameWidth * i),
                yOffset,
                frameWidth,
                frameHeight);

                FPS[i] = _framePerSecond;
                Offsets[i] = Vector2.Zero;
            }
            FramesPerSecond = _framePerSecond;
            PlayOnce = _playOnce;
            drawingOffset = _drawingOffset;
            
            Reset();
        }

        public Animation(int frameCount, int frameWidth, int frameHeight, int xOffset,
            int yOffset, Vector2 _drawingOffset, bool _playOnce, int _framePerSecond, int _textureWidth)
        {
            frames = new Rectangle[frameCount];
            this.frameWidth = frameWidth;
            this.frameHeight = frameHeight;
            Offsets = new Vector2[frameCount];
            FPS = new int[frameCount];

            for (int i = 0; i < frameCount; i++)
            {
                frames[i] = new Rectangle(
                xOffset + (frameWidth * i) % _textureWidth,
                yOffset + (frameWidth * i) / _textureWidth,
                frameWidth,
                frameHeight);

                FPS[i] = _framePerSecond;
                Offsets[i] = Vector2.Zero;
            }
            FramesPerSecond = _framePerSecond;
            PlayOnce = _playOnce;
            drawingOffset = _drawingOffset;
            Reset();
        }
        private Animation(Animation animation)
        {
            PlayOnce = animation.PlayOnce;
            drawingOffset = animation.drawingOffset;
            this.frames = animation.frames;
            this.FPS = animation.FPS;
            this.Offsets = animation.Offsets;
        }

        public void Update(GameTime gameTime)
        {
            if(!IsFinished)
            {
                frameTimer += gameTime.ElapsedGameTime;
                if (frameTimer.TotalSeconds >= 1f / FPS[currentFrame])
                {
                    frameTimer = TimeSpan.Zero;
                    if (PlayOnce)
                    {
                        if (currentFrame + 1 > FrameCount - 1)
                            IsFinished = true;
                        else
                            currentFrame++;
                    }
                    else
                        currentFrame = (currentFrame + 1) % FrameCount;
                }
            }
        }
        public void Reset()
        {
            currentFrame = 0;
            frameTimer = TimeSpan.Zero;
            IsFinished = false;
        }

        public object Clone()
        {
            Animation animationClone = new Animation(this);
            animationClone.frameWidth = this.frameWidth;
            animationClone.frameHeight = this.frameHeight;
            animationClone.FramesPerSecond = this.FramesPerSecond;
            animationClone.PlayOnce = this.PlayOnce;
            animationClone.Reset();
            return animationClone;
        }
    }
}